use std::sync::Arc;
use anyhow::Result;

use crate::di::{ServiceContainer, services::ConfigService};
use crate::config::{Configs, Server, DataBase, Log, Jwt, Cert};

/// 创建测试配置
fn create_test_config() -> Configs {
    Configs {
        server: Server {
            name: "test-server".to_string(),
            address: "127.0.0.1:8080".to_string(),
            ssl: false,
        },
        database: DataBase {
            database_url: "sqlite::memory:".to_string(),
        },
        log: Log {
            filter_level: "info".to_string(),
            with_ansi: true,
            to_stdout: true,
            directory: "./logs".to_string(),
            file_name: "test.log".to_string(),
            rolling: "daily".to_string(),
        },
        jwt: Jwt {
            jwt_secret: "test_secret".to_string(),
            jwt_exp: 3600,
        },
        cert: Cert {
            cert: "test.pem".to_string(),
            key: "test.key".to_string(),
        },
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::atomic::{AtomicUsize, Ordering};

    #[tokio::test]
    async fn test_basic_service_container() {
        let container = ServiceContainer::new();
        
        // 测试服务注册和解析
        container.register_singleton::<ConfigService, _>(|_| {
            let config = create_test_config();
            Ok(ConfigService::new(config))
        }).unwrap();
        
        // 解析服务
        let config_service = container.resolve::<ConfigService>().unwrap();
        assert_eq!(config_service.config().server.name, "test-server");
        
        // 测试单例行为
        let config_service2 = container.resolve::<ConfigService>().unwrap();
        assert!(Arc::ptr_eq(&config_service, &config_service2));
    }

    #[tokio::test]
    async fn test_transient_services() {
        let container = ServiceContainer::new();
        let counter = Arc::new(AtomicUsize::new(0));
        
        // 注册瞬态服务
        let counter_clone = Arc::clone(&counter);
        container.register_transient::<TestService, _>(move |_| {
            let id = counter_clone.fetch_add(1, Ordering::SeqCst);
            Ok(TestService::new(id))
        }).unwrap();
        
        // 解析两次，应该得到不同的实例
        let service1 = container.resolve::<TestService>().unwrap();
        let service2 = container.resolve::<TestService>().unwrap();
        
        assert_ne!(service1.id(), service2.id());
        assert!(!Arc::ptr_eq(&service1, &service2));
    }

    #[tokio::test]
    async fn test_service_dependencies() {
        let container = ServiceContainer::new();
        
        // 注册配置服务
        container.register_singleton::<ConfigService, _>(|_| {
            let config = create_test_config();
            Ok(ConfigService::new(config))
        }).unwrap();
        
        // 注册一个依赖于配置服务的服务
        container.register_singleton::<DependentService, _>(|container| {
            let config_service = container.resolve::<ConfigService>()?;
            Ok(DependentService::new(config_service))
        }).unwrap();
        
        // 解析依赖服务
        let dependent_service = container.resolve::<DependentService>().unwrap();
        assert_eq!(dependent_service.get_server_name(), "test-server");
    }

    #[tokio::test]
    async fn test_service_not_registered() {
        let container = ServiceContainer::new();
        
        // 尝试解析未注册的服务
        let result = container.resolve::<TestService>();
        assert!(result.is_err());
    }

    #[tokio::test]
    async fn test_multi_threaded_access() {
        use tokio::task;
        
        let container = Arc::new(ServiceContainer::new());
        
        // 注册服务
        container.register_singleton::<ConfigService, _>(|_| {
            let config = create_test_config();
            Ok(ConfigService::new(config))
        }).unwrap();
        
        // 创建多个任务并发访问容器
        let mut handles = Vec::new();
        for i in 0..10 {
            let container_clone = Arc::clone(&container);
            let handle = task::spawn(async move {
                let config_service = container_clone.resolve::<ConfigService>().unwrap();
                assert_eq!(config_service.config().server.name, "test-server");
                i
            });
            handles.push(handle);
        }
        
        // 等待所有任务完成
        for handle in handles {
            handle.await.unwrap();
        }
    }

    // 测试用的辅助结构
    #[derive(Debug)]
    struct TestService {
        id: usize,
    }
    
    impl TestService {
        fn new(id: usize) -> Self {
            Self { id }
        }
        
        fn id(&self) -> usize {
            self.id
        }
    }
    
    #[derive(Debug)]
    struct DependentService {
        config_service: Arc<ConfigService>,
    }
    
    impl DependentService {
        fn new(config_service: Arc<ConfigService>) -> Self {
            Self { config_service }
        }
        
        fn get_server_name(&self) -> &str {
            &self.config_service.config().server.name
        }
    }
}
